<?php


use Exception;

/**
 * Class ICBCPay
 * 工银支付
 */

/*include_once 'DefaultIcbcClient.php';
include_once 'ICBCEPayBizContentParameter.php';
include_once 'ICBCPayBizContentParameter.php';*/

/**
 * 功能说明：自定义工商银行支付接入类
 */
class ICBCPay
{
    /*function __construct()
    {
        //引入文件
        require_once(ROOT_PATH . 'data/extend/icbc/icbc-api-sdk-cop-php/DefaultIcbcClient.php');
        require_once(ROOT_PATH . 'data/extend/icbc/icbc-api-sdk-cop-php/UiIcbcClient.php');
    }*/

    public function index()
    {
        // 防止默认目录错误
    }


    /**
     * 基本设置读取
     *
     * @return unknown
     */
    public function getIcbcpayConfig()
    {
        // 工商银行appid（颁发的必填参数）
        $icbc_config['appid'] = '11000000000000016036';

        // 工商银行商户账号(商户线下档案编号(特约商户12位，特约部门15位))
        $icbc_config['mer_id'] = '440248170080';

        // e生活档案编号
        $icbc_config['store_code'] = '440248170080';

        // 接口号，目前仅支持上送1.0.0.1
        $icbc_config['interface_version'] = '1.0.0.1';

        // 第三方应用ID；商户在微信公众号内接入时必送,此处设定为微信公众号的appid
        $icbc_config['tp_app_id'] = 'wxd4887d676c7ee0d6';

        // 网关公钥
        $icbc_config['icbc_pulic_key'] = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRgTG1jjeO39CIMB/gRK
UmiBLkXIHrMbJC/MGAF2/k8BLc6hk+jdDZHJ7aO+QBYyku4LXwDSs35I47dlZdY8
GsifC+gleTNvJuzKxhMu4u3v9Qbb8/RkJabbklAY9JefUD0fdLMEF70TkYLO5X4M
LLjcIspkpftn1SxKF53jLh1fKGdcyP+fwSw+ZUClVw6Xmp63dqwRt2cyO3l5yMW7
z60H218pFvuAJy1rePyhGXoP9wC8a0XXk3SyEQjNT6rxSRhgJB365COMsFFiLi6J
8/peMtXvsRLAFNoDXlXy9mQaiWAb3vjv2kaS9SRpTImR7ulDj/xVSYhBZCQ4uoxS
AwIDAQAB';

        // 应用私钥
        $icbc_config['private_key'] = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5GBMbWON47f0I
gwH+BEpSaIEuRcgesxskL8wYAXb+TwEtzqGT6N0Nkcnto75AFjKS7gtfANKzfkjj
t2Vl1jwayJ8L6CV5M28m7MrGEy7i7e/1Btvz9GQlptuSUBj0l59QPR90swQXvROR
gs7lfgwsuNwiymSl+2fVLEoXneMuHV8oZ1zI/5/BLD5lQKVXDpeanrd2rBG3ZzI7
eXnIxbvPrQfbXykW+4AnLWt4/KEZeg/3ALxrRdeTdLIRCM1PqvFJGGAkHfrkI4yw
UWIuLonz+l4y1e+xEsAU2gNeVfL2ZBqJYBve+O/aRpL1JGlMiZHu6UOP/FVJiEFk
JDi6jFIDAgMBAAECggEAIVuAXgZYAHxLhNQvcLsPNejVlyRGW5oFwzDGBHGHI2/T
k5DQt9pYtFBY5vYCnIQjmy1BaV65mlWhB0EPChpg/Ka5Wyj8T+qAFrDIHohog8dD
3pHc5AtgXRTEL4s15CbLNGe/moWEsE6ID0pWxS9BPHIYYkC9gNhdLyLrO3Rd8/pS
EdAZCewU6+3K0hWwRO/0fVQTI+huNr4kfqkK/0x5G8IlVOlIZYvUysSPwXjFr+aa
00dAVhKEZOUY1x0Aau2CLjE/tAbK3OaTUjKNvgFLjkvB0LsuejcTDP99c3LbqZVr
pLdOgPLlE2ho2Ehfi6XCQioNhg5cOvxazHla1zE5EQKBgQDAQFUyx6vHF+gN9TBI
J8FnLIeMUIcWAV/48tLF9BK/Hu89/S9ysuvBj8uCVdP9xtDTEJDGlf0L5YkXY8ko
kYiOqE/HJBXr1tTcwEmLgl9TJsOCwr9vvPR2mMk6mv6kURGd3x+T2DpW6jGFoBLt
lTAQc706jn7tr8VRUEScalcLOQKBgQD2eC62gA6TzOfhzfgq16/+s72kT54TxCcD
8lSxWj+gHNlr/lacpR/BOQDL8NcdrwhJlRcq16v4D2yYnPPg//vS2DJOtwUzO9Ve
fS3V7A1uFLvqcqVEQLn4gZ/OUCep7hql4yvDILPCcDZs98ECQCzsRiusaLqhKUHN
9yEl6gg7GwKBgBjwv5zE1n4PleUpp8fUkHyIBFWppLywFPlA1yMjFMOCidrq25rv
pzIHK4mPBN9pSXH4Ni/tCVTfxDcqlNAUgTiwkRjuj4F270psD55vnVo2LyrphNhE
FRrFm2Vk8h/y/GwUpA4UAQ2BeEcziwETV5bqzOOp1MGVCe4QkbYQ/ZXRAoGBAKj5
nnUKeHQGQFfEAUdGFmgVzIeQ+jxs956yDjSFPifEf5+VgMXmQ04SiaRIWwMD1De2
WmrJ8CGiWX6L5Hu2pGxaQqtKuOr2M4OTaNBIBLEaz/adYQbZJWblX61vsLHFB0oB
5CfkDLnaesXcWdv0KZhXR2vtZT5GbdIKgxReTgRPAoGAHVBZMkn/bYPJMF8QJ6Gr
CF9qsvWe++B4Q/Mk6Ohca81k+GIwiVSjcB/BhPLUev4Ph75P76HTJA4pFBJIBMUA
8GlnI69I1rtRZN2NHQ7SxArTu6IVomgZAL3tnwLeP1ltcGXN6+csAFnioOS7a3qJ
bC/ctrMMfMibepX5lKd6dQo=';

        // 应用私钥
        $icbc_config['encrypt_key'] = '';

        return $icbc_config;
    }

    /**
     * @param $msg_id //消息通讯唯一编号，每次调用独立生成，APP级唯一
     * @param $tp_open_id //第三方用户标识；商户在微信公众号/支付宝生活号内接入时必送，上送用户在商户appid下的唯一标识。
     * @param $out_trade_no //商户订单号；需保证商户系统唯一
     * @param string $tran_type //交易类型 OfflinePay-线下支付，OnlinePay-线上支付
     * @param $goods_body //商品描述  芬达
     * @param $goods_detail //商品详情  {‘good_name’:’芬达橙味300ml罐装’,’good_id’:’1001’,’good_num’:’1’}
     * @param $order_amount // 总金额（单位：分）
     * @param $return_url // 支付成功回显页面。支付成功后，客户端引导跳转至该页面显示
     * @param $notify_url // 支付结果通知地址；
     * @param $mer_hint // 商家提示。目前暂无处理，后续可用于在交易页面回显给客户
     * @param $attach // 附加数据。商户可上送定制信息
     * @return string
     * 当前接口参数类型全部为字符串类型，调用时注意！
     */
    public function setAPV2Pay($msg_id, $tp_open_id, $out_trade_no, $tran_type = 'OnlinePay', $goods_body, $goods_detail, $order_amount, $return_url, $notify_url, $mer_hint, $attach)
    {

        $icbc_config = $this->getIcbcpayConfig();

        //第三方应用ID；商户在微信公众号内接入时必送，上送微信分配的公众账号ID；商户通过支付宝生活号接入时必送，上送支付宝分配的应用ID。
        $tp_app_id = $icbc_config['tp_app_id'];

        //分期期数。目前仅支持1-不分期,注意必须是字符串类型
        $install_times = '1';

        //通知类型，表示在交易处理完成后把交易结果通知商户的处理模式。 取值“HS”：在交易完成后将通知信息，主动发送给商户，发送地址为notify_url指定地址； 取值“AG”：在交易完成后不通知商户
        $notify_type = 'HS';

        //结果发送类型，通知方式为HS时有效。取值“0”：无论支付成功或者失败，银行都向商户发送交易通知信息；取值“1”，银行只向商户发送交易成功的通知信息，注意必须是字符串类型
        $result_type = '0';


        $content = array(
            "interface_version" => (string)$icbc_config['interface_version'],
            "mer_id" => (string)$icbc_config['mer_id'],
            "tp_app_id" => (string)$tp_app_id,
            "tp_open_id" => (string)$tp_open_id,
            "out_trade_no" => (string)$out_trade_no,
            "tran_type" => (string)$tran_type,
            "order_date" => (string)date("YmdHis", $_SERVER['REQUEST_TIME']),
            "end_time" => (string)date("YmdHis", $_SERVER['REQUEST_TIME'] + 300),  // order_date之后5分钟
            "goods_body" => (string)$goods_body,
            "goods_detail" => (string)$goods_detail,
            "order_amount" => (string)bcmul($order_amount, 100), //总金额(单位分)
            "spbill_create_ip" => (string)$_SERVER['REMOTE_ADDR'],
            "install_times" => (string)$install_times,
            "return_url" => (string)$return_url, // 支付回显
            "notify_url" => (string)$notify_url, // 支付结果通知
            "notify_type" => (string)$notify_type,
            "result_type" => (string)$result_type,
        );

        if (!empty($attach)) $content['attach'] = $attach;
        if (!empty($mer_hint)) $content['mer_hint'] = $mer_hint;


        //接口调用地址
        $serviceUrl = 'https://gw.open.icbc.com.cn/ui/aggregate/payment/request/V2';

        //调用参数合集
        $request = array(
            "serviceUrl" => $serviceUrl,
            "method" => 'POST',// 请求方法，只能是POST或GET
            "isNeedEncrypt" => true,// 是否需要加密
            "extraParams" => null,//其他参数,用数组类型array
            "biz_content" => $content,
        );

        //组成form表单提交
        $resp = $this->icbcClientForm($icbc_config, $request, $msg_id);

        return $resp;
    }


    /**
     * 工商银行获取支付二维码
     * 当前接口参数类型全部为字符串类型，调用时注意。
     */
    public function getPayQrCode($msg_id, $out_trade_no, $pay_expire, $order_amt, $notify_url, $attach)
    {
        $icbc_config = $this->getIcbcpayConfig();

        //商户是否开启通知接口 0-否；1-是；非1按0处理，注意必须是字符串类型
        $notify_flag = '1';

        //扫码后是否需要跳转分行，0：否，1：是；非1按0处理，注意必须是字符串类型
        $sp_flag = '0';

        $content = array(
            'mer_id' => (string)$icbc_config['mer_id'],
            'out_trade_no' => (string)$out_trade_no,
            'store_code' => (string)$icbc_config['store_code'],//e生活档案编号
            'order_amt' => (string)bcmul($order_amt, 100), //总金额(单位分)
            'trade_date' => (string)date("Ymd", $_SERVER['REQUEST_TIME']),  //订单生成日期
            'trade_time' => (string)date("His", $_SERVER['REQUEST_TIME']),  //订单生成时间
            'tporder_create_ip' => (string)$_SERVER['REMOTE_ADDR'],
            'notify_url' => (string)$notify_url, // 支付结果通知
            'notify_flag' => (string)$notify_flag,
            'sp_flag' => (string)$sp_flag,
            'pay_expire' => (string)$pay_expire,//二维码过期时间
        );

        if (!empty($attach)) $content['attach'] = $attach;

        //接口调用地址
        $serviceUrl = 'https://gw.open.icbc.com.cn/api/qrcode/V2/generate';

        //调用参数合集
        $request = array(
            "serviceUrl" => $serviceUrl,
            "method" => 'POST',// 请求方法，只能是POST或GET
            "isNeedEncrypt" => false,// 是否需要加密
            "extraParams" => null,//其他参数,用数组类型array
            "biz_content" => $content,
        );

        //进行curl提交，并获取返回值
        $resp = $this->icbcClientCurl($icbc_config, $request, $msg_id);

        return $resp;
    }


    /**
     * 建立请求，提交信息,公众号聚合支付 构造form表单
     * @param $icbc_config
     * @param $json_content
     * @param $msg_id
     */
    public function icbcClientForm($icbc_config, $request, $msg_id)
    {

        //APP的编号,应用在API开放平台注册时生成
        $appId = $icbc_config['appid'];

        //应用私钥
        $privateKey = $icbc_config['private_key'];

        //签名类型，CA-工行颁发的证书认证，RSA-RSAWithSha1，RSA2-RSAWithSha256，缺省为RSA2，
        $signType = \IcbcConstants::$SIGN_TYPE_RSA2;

        //字符集 ,缺省为UTF-8
        $charset = 'UTF-8';

        //请求参数格式，仅支持json
        $format = 'json';

        //网关公钥
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        //AES加密密钥，缺省为空
        $encryptKey = $icbc_config['encrypt_key'];

        //加密方式，本接口参数需进行AES加密
        $encryptType = 'AES';

        //采用ca认证方式时，需上送证书,使用此签名算法的时候，php需要安装扩展php_infosec.dll，工行sdk提供的是php7.0以上的版本
        $ca = '';

        //当签名类型为CA时，通过该字段上送证书密码，缺省为空
        $password = '';

        //初始化链接请求构造
        $client = new \UiIcbcClient($appId, $privateKey, $signType, $charset, $format,
            $icbcPulicKey, $encryptKey, $encryptType, $ca, $password);

        //请求接口下单
        $resp = $client->buildPostForm($request, $msg_id, '');

        return $resp;
    }

    /**
     * 建立请求，提交信息,构造curl请求
     * @param $icbc_config
     * @param $json_content
     * @param $msg_id
     */
    public function icbcClientCurl($icbc_config, $request, $msg_id)
    {

        //APP的编号,应用在API开放平台注册时生成
        $appId = $icbc_config['appid'];

        //应用私钥
        $privateKey = $icbc_config['private_key'];

        //签名类型，CA-工行颁发的证书认证，RSA-RSAWithSha1，RSA2-RSAWithSha256，缺省为RSA2，
        $signType = \IcbcConstants::$SIGN_TYPE_RSA2;

        //字符集 ,缺省为UTF-8
        $charset = 'UTF-8';

        //请求参数格式，仅支持json
        $format = 'json';

        //网关公钥
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        //AES加密密钥，缺省为空
        $encryptKey = $icbc_config['encrypt_key'];

        //加密方式，本接口参数需进行AES加密
        $encryptType = 'AES';

        //采用ca认证方式时，需上送证书,使用此签名算法的时候，php需要安装扩展php_infosec.dll，工行sdk提供的是php7.0以上的版本
        $ca = '';

        //当签名类型为CA时，通过该字段上送证书密码，缺省为空
        $password = '';

        //初始化链接请求构造 此处注意，工行官网sdk文件中提供的【IcbcSignature::verify】方法缺失参数，需要补上$password参数，否则无法调用成功。
        $client = new \DefaultIcbcClient($appId, $privateKey, $signType, $charset, $format,
            $icbcPulicKey, $encryptKey, $encryptType, $ca, $password);

        //请求接口下单
        $resp = $client->execute($request, $msg_id, '');

        $resp = $resp ? json_decode($resp, true) : '';

        return $resp;
    }

    /**
     * * 回调签名验证
     * @param $postArr   工行返回参数
     * @param $notify_url  回调url
     * @return int|void
     * @throws Exception
     */
    public function icbcCheckSign($postArr, $notify_url)
    {
        $icbc_config = $this->getIcbcpayConfig();

        //工行以数组返回
        $postParame = $postArr;
        $sign = $postParame['sign'];
        unset($postParame['sign']);
        //进行验签操作
        $WebUtils = new \WebUtils();
        $IcbcSignature = new \IcbcSignature();
        $path = parse_url($notify_url, PHP_URL_PATH);
        $content = $WebUtils->buildOrderedSignStr($path, $postParame);

        //签名类型，CA-工行颁发的证书认证，RSA-RSAWithSha1，RSA2-RSAWithSha256，缺省为RSA2，
        $signType = \IcbcConstants::$SIGN_TYPE_RSA;

        //字符集 ,缺省为UTF-8
        $charset = \IcbcConstants::$CHARSET_UTF8;

        //当签名类型为CA时，通过该字段上送证书密码，缺省为空
        $password = '';

        //网关公钥
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        (boolean)$signVerified = $IcbcSignature->verify($content, $signType, $icbcPulicKey, $charset, $sign, $password);

        return $signVerified;
    }

    /**
     * 请求最原始的demo
     */
    public function demo($data)
    {
        include_once('UiIcbcClient.php');
        $msg_id = 'aa' . rand(10000000, 999999999);
        $config=$this->getIcbcpayConfig();
        $content = array(
            "interface_version" => "1.0.0.1",
            "mer_id" =>$config["mer_id"],
            "tp_app_id" => $config["appid"],
            "tp_open_id" => $data["open_id"],
            "out_trade_no" => '12311212',
            "tran_type" => "OfflinePay",
            "order_date" => date("YmdHis", $_SERVER['REQUEST_TIME']),
            "end_time" => date("YmdHis", $_SERVER['REQUEST_TIME'] + 300),  // order_date之后5分钟
            "goods_body" => '12',
            "goods_detail" => "{'good_name':1,'good_id':2,'good_num':'1'}",
            "order_amount" => bcmul(0.01, 100), //总金额(单位分)
            "spbill_create_ip" => $_SERVER['REMOTE_ADDR'],
            "install_times" => "1",
            "return_url" => "http://ip/index/pay/successful", // 支付回显
            "notify_url" => "http://ip/index/pay/notify", // 支付结果通知
            "notify_type" => "HS",
            "result_type" => "0",
        );
        $orig_date=date("Y-m-d",time());
        $orig_time=date("H:i:s",time());
        $orig_date_time=$orig_date."T".$orig_time;
        $biz_content=[
            "mer_id"=>"440248170080",
            "out_trade_no"=>$order["order_sn"],
            "pay_mode"=>'9',
            "access_type"=>'9',
            "mer_prtcl_no"=>'440248170080',
            "orig_date_time"=>$orig_date_time,
            "decive_info"=>"440248170080",
            "body"=>"成都本草之源生物科技有限公司"."商品",
            "fee_type"=>'001',
            "spbill_create_ip"=>request()->ip(),
            "total_fee"=>'100',
            "mer_url"=>$mer_url,
            "shop_appid"=>'wxd4887d676c7ee0d6',
            "icbc_appid"=>'11000000000000016036',
            "open_id"=>$openid,
            "expire_time"=>'1800',
            "notify_type"=>"HS",
            //非必填参数
            "union_id"=>"",
            "mer_acct"=>"",
            "attach"=>"",
            "result_type"=>"",
            "pay_limit"=>"",
            "order_apd_inf"=>"",
            "detail"=>"",
            "return_url"=>"",
            "quit_url"=>"",
        ];
        $data=[
            "app_id"=>"11000000000000016036",
            "msg_id"=>$order["order_sn"],
            "sign"=>"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCssav8hbwKkjVxj3nojQ6HHe7+cCvWPNvbQFDzYJtIRetqxW3AzSB1Gfe7J8MgzMy4BnIWJRiIzEqapxxeFo2oJ7clILY1gkmyyYfFFQLNX0Fooy8sv+EJ2GxHZr4io5Idy0ALN1ctPXFVZaI1OSxn8N06MixQJImzo3ObHVkCHOtzifUAeH+rDYh5XKACQ1dcACi2YPibZdm3rK67Xuguzmbf2NnEJIjMhI/vbq50n0eR+601r9t64BuKqBgu5UXKyzPHgcN3OEbJZQ0ScvKYfguAHNy/E3UM0r8TkceF9WtzuGzGSmOO3BLnT01xz/VajkXgAIzYHVa35kNKbw8LAgMBAAECggEAVFZ4zdxqFyeMXidZvA6XV7lwrGYPopMaNBtW7WTysPskm4JLtWr4PPgvmgEzNGOQXxcWxGXdc4GBtcGDAxg0mji7IrC1C7DTWTM+0SsPsUih4v4+3bXfqzU8vCobFUOY6mAGqPOf6YImRTRbYW7IlwJ0qCU0qvcNIOPkY46Tl4nGZ4/PNBNM7Yb6F5Eq4zC8ANJwnHXHs7VExf9N/bNELezEnOIuqjKuAUa7rlh++0ma/iTjGOgvDBj1RhRgMkbeQsgK18xzv5ZUG7+70ZNK5q97vNrXYKHSDzcrp1hUTgZlMGOOqhHUm20EF2syol9R+5QIjAjmY+S6qhYbXn/IgQKBgQDGrE6uhs5S6XcUZAUC7zzV/uRTx+3hqlc4CJs1ha8nC9QpHZHlhD6z8ybHe2lAy8biS9Qc+XSDZCk1naKVanMtt4sh31MSBHaQ4Lg0jb6LhDCHDesgM2+t7/NTiX7knAj28gBrfagBWAltr45F6qUxhX4WOPAvjB3sJI4xqmPuawKBgQDehlR6/ow8hcqrs1m8zzuvkQwkq1bKJOVKnjkIviWa9VCCPq3yR2fWYplEqUowWEOCX+UJt9isymSI3O5syEKstMUCDiIG87EfxsNG61EKnefqwptIaVUloXpgRfmEl7WfqQynGHq4v3TLeqi+22hZv701bU2dEhBJ5zXKqFpJ4QKBgQC/fEgB0xB9vWP2lUh3QZrDLv9m+OYAgSu7aCAggA8HdVExp7x9GO9Ohec0kXAq8b1pU2jH3G8+TIWjlaGknYsR3zwMk7D/Rqn4jX89t/iVg/05zmJ3ENxtKz69n2JceT/ys+FPuTb6xJ2hyHk6TiSWDHIwfQSS71vPxJQArpfOrQKBgHEjaUaTr2eCOtZrvN+DmfwcykjGmLz0X2Q96A+q5eHQgluGVNiPN5tHzFednyvPZJuf+Aql39OSn+T6N3s1ori+vD/cQa65LkBSxayELlMwj97LjToW3ATjAh561W911xFTWSyIBLV0GoTuW2eWlIq1MxU7+q82pPN+S9o7GJThAoGAdUM1lApxS+Zn4p0MDIKzoIHNE5JkNXJFwxp4o0cbnfyEEZqdVruX80D8hyKgPDnYuCeDLBqnKBkrdfq8jNTFDEBmFk+V4+HRj/7aL2WXKOkW3O1AOz+yjTHhSFwc4He1jKCAz585aKWQG1TWPHlnp2QzGlqpsD/W3tIjO9etYIc=",
            "timestamp"=>$orig_date." ".$orig_time,
            "biz_content"=>$biz_content,
            "sign_type"=>"RSA2",
            //非必填参数
            /*"format"=>"json",
            "charset"=>"UTF-8",
            "encrypt_type"=>"AES",
            "ca"=>"",*/
        ];

        $request = array(
            "serviceUrl" => 'https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1',
            "method" => 'POST',
            "isNeedEncrypt" => true,
            "extraParams" => null,
            "biz_content" => $content,
            "app_id" => $config["app_id"],
            "msg_id" => $config["msg_id"],
        );
        $client = new \UiIcbcClient('appid',
            '私钥key',
            \IcbcConstants::$SIGN_TYPE_RSA2,
            'UTF-8',
            'json',
            '网关公钥',
            'AES加密key',
            'AES',
            '',
            '');
        $resp = $client->buildPostForm($request, $msg_id, '');
        echo $resp;
        die;
    }
}

